home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CPPTASK.ARJ / TSKASM.ASM < prev    next >
Assembly Source File  |  1991-07-26  |  7KB  |  357 lines

  1. ;
  2. ;    CTask - Scheduler and miscellaneous utilities
  3. ;
  4. ;    Public Domain Software written by
  5. ;        Thomas Wagner
  6. ;        Patschkauer Weg 31
  7. ;        D-1000 Berlin 33
  8. ;        West Germany
  9. ;
  10.  IFDEF at
  11. .186
  12.  ENDIF
  13.     name    tskasm
  14.     .model    large
  15. ;
  16.         public  _asm_schedule
  17.     public    _asm_c_schedule
  18.         public  scheduler
  19.     public    _sched_int
  20. ;
  21.     public    _tsk_dis_int
  22.     public    _tsk_ena_int
  23.     public    _tsk_flags
  24.     public    _tsk_nop
  25. ;
  26. ;
  27.     include    tsk.mac
  28. ;
  29. INT_FLAG    =    2h    ; Int enable flag in upper byte of flag reg
  30. r_flags        =    24    ; Offset of flag register on task stack
  31. ;
  32.     extrn    _tsk_current: dword
  33.         extrn   _tsk_eligible: dword
  34.     extrn    _tsk_preempt: byte
  35.     extrn    _tsk_pretick: byte
  36.     extrn    _tsk_var_prior: byte
  37. ;
  38.     .data
  39. ;
  40. in_sched    db    0
  41. ;
  42.     .code
  43. ;                   
  44. _dgroup        dw    seg dgroup
  45. ;
  46. ;------------------------------------------------------------------------
  47. ;
  48. ;    enq    Enqueue tcb in queue. For local use only.
  49. ;        entry:    es:di = tcb to enqueue
  50. ;        exit:    -
  51. ;        uses:    ax, cx, dx, bp, di
  52. ;
  53. enq    macro
  54. ;
  55.     lds    bx,es:queue[di]        ; queue head pointer
  56.     mov    ax,ds
  57.     or    ax,bx    
  58.     jz    enq_end            ; nothing left to do if queue null
  59.     mov    dx,es:prior[di]        ; load priority of task
  60. enq_l:
  61.     mov    cx,bx            ; save last ptr
  62.     mov    bp,ds
  63.     lds    bx,next[bx]        ; load next
  64.     mov    ax,ds
  65.     or    ax,bx            ; end of chain?
  66.     jz    enq_found        ; then insert
  67.     cmp    dx,prior[bx]        ; compare priority
  68.     jbe    enq_l            ; loop if tasks prior less or equal
  69. ;
  70. enq_found:
  71.         mov     word ptr es:next[di],bx    ; set tasks next pointer
  72.         mov     word ptr es:next+2[di],ds
  73.         mov     bx,cx                      ; last pointer
  74.     mov    ds,bp
  75.         mov     word ptr next[bx],di       ; last->next = task
  76.     mov    word ptr next+2[bx],es
  77. enq_end:
  78.     mov    ds,_dgroup
  79. ;
  80.     endm
  81. ;
  82. ;
  83. ;    upd_prior: Update priority of tasks in eligible queue.
  84. ;               Only activated if tsk_var_prior is nonzero.
  85. ;
  86. ;    NOTE:    This loop is not protected by interrupt disable.
  87. ;        Since it does not modify the queue itself, there
  88. ;        is no danger of race conditions.
  89. ;
  90. upd_prior    macro
  91. ;
  92.     les     di,_tsk_eligible
  93. pinc_loop:
  94.     mov    ax,es
  95.     or    ax,di            ; end of chain?
  96.     jz    updp_end
  97.     inc    es:prior[di]
  98.     jnz    pinc_nxt
  99.     dec    es:prior[di]
  100. pinc_nxt:
  101.     les    di,es:next[di]
  102.     jmp    pinc_loop
  103. ;
  104. updp_end:
  105. ;
  106.     endm
  107. ;
  108. ;
  109. ;    The scheduler. Note that this routine is entered with the stack
  110. ;    set up as for an interrupt handler.
  111. ;
  112. scheduler    proc    far
  113. ;
  114.     cli            ; better safe than sorry
  115.     push    ds
  116.     mov    ds,_dgroup
  117.     cmp    in_sched,0    ; already in the scheduler?
  118.     je    sched_ok    ; continue if not
  119.     pop    ds        ; else return immediately
  120.     iret
  121. ;
  122. sched_ok:
  123.     inc    in_sched
  124.     pop    ds
  125. ;    sti            ; we can now safely enable interrupts
  126.  IFNDEF at
  127.     push    ax
  128.     push    cx
  129.     push    dx
  130.     push    bx
  131.     push    sp
  132.     push    bp
  133.     push    si
  134.     push    di
  135.  ELSE
  136.     pusha
  137.  ENDIF
  138.     push    ds
  139.     push    es
  140. ;
  141.         mov     ds,_dgroup             ; establish addressing of our vars
  142. ;
  143.     cmp    _tsk_var_prior,0
  144.     je    no_var_pri
  145.         upd_prior                      ; update priority
  146. ;
  147. no_var_pri:
  148.         cli                            ; the following is critical
  149. ;
  150.         les     di,_tsk_current        ; get current tcb
  151.         mov     ax,es                  ; check if NULL (current task killed)
  152.     or    ax,di
  153.     jz    no_current
  154. ;
  155.     mov    word ptr es:tcbstack[di],sp ; store stack pointer & seg
  156.     mov    word ptr es:tcbstack+2[di],ss
  157. ;
  158.     cmp    es:state[di],ST_RUNNING
  159.     jne    not_eligible
  160.     mov    es:state[di],ST_ELIGIBLE
  161. not_eligible:
  162. ;
  163.         enq                             ; Enqueue current task
  164. ;
  165. no_current:
  166.     mov    _tsk_pretick,0        ; No preemption tick
  167.     and    _tsk_preempt,1        ; Turn off temp preempt flag
  168. ;
  169. wait_elig:
  170.     cli
  171.         les     di,_tsk_eligible
  172. ;
  173. ;    If eligible queue empty, enter waiting loop
  174. ;
  175.     mov    ax,es
  176.     or    ax,di            ; is the eligible queue empty?
  177.     jnz    not_empty        ; jump if not
  178.     sti                       ; enable interrupts
  179.     nop
  180.     nop
  181.     jmp    wait_elig
  182. ;
  183. ;    Eligible queue not empty, activate first eligible task.
  184. ;
  185. not_empty:
  186.         mov     ax,word ptr es:next[di]         ; load next pointer
  187.         mov     word ptr _tsk_eligible,ax       ; remove from queue
  188.     mov    ax,word ptr es:next+2[di]
  189.         mov     word ptr _tsk_eligible+2,ax
  190. ;
  191.         mov     word ptr _tsk_current,di        ; set tcb into current
  192.     mov    word ptr _tsk_current+2,es
  193.         mov     ax,es:iniprior[di]              ; reset current tasks priority
  194.     mov    es:prior[di],ax
  195. ;
  196.         mov     in_sched,0                      ; reset scheduler active flag
  197. ;
  198.         lds     si,es:tcbstack[di]              ; load stack
  199.     or    byte ptr r_flags+1[si],INT_FLAG    ; enable interrupts
  200.         mov     es:state[di],ST_RUNNING         ; set task state
  201.         mov     cx,ds                           ; switch stack
  202.     mov    ss,cx
  203.     mov    sp,si
  204.         pop     es                              ; restore all registers
  205.     pop    ds
  206.  IFNDEF at
  207.     pop    di
  208.     pop    si
  209.     pop    bp
  210.         pop     bx                              ; don't pop SP
  211.     pop    bx
  212.     pop    dx
  213.     pop    cx
  214.     pop    ax
  215.  ELSE
  216.     popa
  217.  ENDIF
  218.     iret
  219. ;
  220. scheduler    endp
  221. ;
  222. ;
  223. ;--------------------------------------------------------------------------
  224. ;
  225. ;
  226. ;    _sched_int  
  227. ;
  228. ;    Is the scheduler entry for interrupt handlers.
  229. ;    It checks if preemption is allowed, returning if not.
  230. ;    The stack is assumed to be set up as on interrupt entry.
  231. ;    
  232. _sched_int    proc    far
  233. ;
  234.     push    ds
  235.     push    bx
  236.     mov    ds,_dgroup
  237.     cmp    _tsk_preempt,0        ; preempt flags 0?
  238.     jne    no_sched        ; no scheduling if set
  239.     lds    bx,_tsk_current        ; current running task
  240.     test    flags[bx],F_CRIT    ; preemption allowed for this task?
  241.     jnz    no_sched        ; no scheduling if flag set
  242.     pop    bx            ; else go schedule
  243.     pop    ds
  244.     jmp    scheduler
  245. ;
  246. no_sched:
  247.     mov    ds,_dgroup
  248.     mov    _tsk_pretick,1        ; Mark preemption pending
  249.     pop    bx
  250.     pop    ds
  251.     iret
  252. ;
  253. _sched_int    endp
  254. ;
  255. ;
  256. ;    void far asm_schedule (void)
  257. ;
  258. ;    Entry for calling the scheduler. Rearranges the stack to
  259. ;    contain flags.
  260. ;    NOTE: Uses ax,bx.
  261. ;
  262. _asm_schedule    proc    far
  263. ;
  264.     pop    ax
  265.     pop    bx
  266.     pushf
  267.     push    bx
  268.     push    ax
  269.     cli
  270.     jmp    scheduler
  271. ;
  272. _asm_schedule    endp
  273. ;
  274. ;
  275. ;    void far asm_c_schedule (void)
  276. ;
  277. ;    Entry for conditionally calling the scheduler. Rearranges 
  278. ;    the stack to contain flags, then jumps to _sched_int.
  279. ;    NOTE: Uses ax,bx.
  280. ;
  281. _asm_c_schedule    proc    far
  282. ;
  283.     pop    ax
  284.     pop    bx
  285.     pushf
  286.     push    bx
  287.     push    ax
  288.     cli
  289.     jmp    _sched_int
  290. ;
  291. _asm_c_schedule    endp
  292. ;
  293. ;    word tsk_flags (void)
  294. ;
  295. ;    Returns current contents of Flag register.
  296. ;
  297. _tsk_flags    proc    far
  298.     pushf
  299.     pop    ax
  300.     ret
  301. _tsk_flags    endp
  302. ;
  303. ;
  304. ;    int tsk_dis_int (void)
  305. ;
  306. ;    Returns current state of the interrupt flag (1 if ints were 
  307. ;    enabled), then disables interrupts.
  308. ;
  309. _tsk_dis_int    proc    far
  310. ;
  311.     pushf
  312.     pop    ax
  313.     mov    cl,9
  314.     shr    ax,cl
  315.     and    ax,1
  316.     cli
  317.     ret
  318. ;
  319. _tsk_dis_int    endp
  320. ;
  321. ;
  322. ;    void far tsk_ena_int (int state)
  323. ;
  324. ;    Enables interrupts if 'state' is nonzero.
  325. ;
  326. _tsk_ena_int    proc    far
  327. ;
  328.     push    bp
  329.     mov    bp,sp
  330.     mov    ax,6[bp]
  331.     pop    bp
  332.     or    ax,ax
  333.     jz    teiend
  334.     sti
  335. teiend:
  336.     ret
  337. ;
  338. _tsk_ena_int    endp
  339. ;
  340. ;    void tsk_nop (void)
  341. ;
  342. ;    Do nothing. Used for very short delays.
  343. ;
  344. _tsk_nop    proc    far
  345. ;
  346.     jmp    short tnop1
  347. tnop1:
  348.     jmp    short tnop2
  349. tnop2:
  350.     ret
  351. ;
  352. _tsk_nop    endp
  353. ;
  354.     end
  355.  
  356.  
  357.